package com.example.springboot.config;

import com.example.springboot.service.Impl.CustomUserDetailsServiceImpl;
import com.example.springboot.utils.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SecurityConfig implements WebMvcConfigurer {
    @Autowired
    private CustomUserDetailsServiceImpl customUserDetailsService;
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter
            =
            //设置jwt的放行路径，以以下内容开头的url就不用进行jwt验证
            new JwtAuthenticationTokenFilter();
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors(core -> core.configurationSource(corsConfigurationSource()))
                .csrf(csrf -> csrf.disable())

                .authorizeHttpRequests(authorize -> authorize
                        //这两个拦截是github授权登入必备的
//                        .requestMatchers("/login1/**","/OAuth21/**").authenticated()
                        .anyRequest().permitAll()
                )
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                .authenticationProvider(authenticationProvider())
                .oauth2Login(oauth2Login ->
                        oauth2Login
                                .loginPage("/index.html")
                                .successHandler(successHandler())

                );
        return http.build();
    }
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("http://localhost:8080");
        configuration.addAllowedOrigin("http://localhost:8081");
        configuration.addAllowedOrigin("http://localhost");
        configuration.addAllowedOrigin("https://github.com");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


    private AuthenticationSuccessHandler successHandler() {
        SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler();
        handler.setDefaultTargetUrl("http://localhost:8080/");  // 设置重定向路径
        return handler;
    }
//    @Bean
//    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//        http
//                // 禁用CSRF保护，因为不使用会话
//                .csrf(csrf -> csrf.disable())
//                // 禁用表单登录
////                .formLogin(f -> f.disable())
//                // 禁用登出功能
////                .logout(l -> l.disable())
//                // 设置会话管理策略为无状态
//                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
//                .authorizeHttpRequests((authorizeRequests -> {
//                    authorizeRequests
//                            .anyRequest().authenticated();
//                            //配置拦截的请求url
////                            .requestMatchers(HttpMethod.GET, "/user/find").authenticated()
//                            // 配置所有请求都将被允许无条件通过
//                            //这个配置我放到下面的ignoring里面了
////                            .anyRequest().permitAll();
//                }))
////                .oauth2Login(ol->ol.clientRegistrationRepository(clientRegistrationRepository)
//                                    //登入成功重定向的url
////                                   .defaultSuccessUrl("http://localhost:8080/home")
////                )
//                .oauth2Login(withDefaults())
//
//                //设置自定义jwt认证拦截器在UsernamePasswordAuthenticationFilter拦截器之前执行
////                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
////                .authenticationProvider(authenticationProvider())
//                // 禁用基本认证
////                .httpBasic(hb -> hb.disable())
//        ;
//        return http.build();
//    }
    @Bean
    public WebSecurityCustomizer ignoringCustomizer() {
//        优先级比authorizeHttpRequests里配置的高，相当于spring security一点都不管
        return (web) -> web.ignoring().requestMatchers("/account/login");
    }
    //密码加密
    @Bean
    public PasswordEncoder passwordEncoder() {
        //密码加密
        return new BCryptPasswordEncoder(10);
    }

    //设置spring security的表单登入的账号密码，这里的禁止了表单登入
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(customUserDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
}